﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Eqwww.App.SystemManage;
using Eqwww.Domain.Models.SystemManage;
using Eqwww.Web.Areas.SystemManage.Models.User;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Eqwww.Code;
using AspNetCore.MultipartRequest;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
using Eqwww.Data;
using Eqwww.App.Authorize;
using Eqwww.App.Identity;
using Eqwww.Domain.Models.Identity;
using AutoMapper;

namespace Eqwww.Web.Areas.SystemManage.Controllers
{
    [Area("SystemManage")]
    public class UserController : ControllerBase
    {
        private AuthorizeApp _authorizeApp;
        private UserApp _userApp;
        private PostApp _postApp;
        private RoleApp _roleApp;
        private IWebHostEnvironment _hostingEnvironment;
        private ApplicationDbContext _context;
        private IMapper _mapper;

        public UserController(RoleApp roleApp
            , AuthorizeApp authorizeApp
            , UserApp userApp
            , PostApp postApp
            , IWebHostEnvironment hosting
            , ApplicationDbContext context
            , IMapper mapper)
        {
            _roleApp = roleApp;
            _authorizeApp = authorizeApp;
            _userApp = userApp;
            _postApp = postApp;
            _hostingEnvironment = hosting;
            _context = context;
            _mapper = mapper;
        }

        [AuthFilter]
        public IActionResult Index(string keyword, Eqwww.Domain.Models.Identity.UserType? userType, int? pageIndex, int? pageSize)
        {
            var currentModuleCode = "SystemManage_User";
            ViewData["SelectedButtons"] = _authorizeApp.GetAuthorizedModuleButtons(User, currentModuleCode, ModuleButtonPosition.Selected);
            ViewData["InitialButtons"] = _authorizeApp.GetAuthorizedModuleButtons(User, currentModuleCode, ModuleButtonPosition.Initial);

            return View();
        }

        [AuthFilter]
        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(string postId, [Bind("UserName, RealName, Contact, Password, RepeatPassword, UserType, Email, SortCode, Avatar")] CreateViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new UserModel
                {
                    UserName = model.UserName,
                    RealName = model.RealName,
                    Email = model.Email,
                    SortCode = model.SortCode,
                    Avatar = model.Avatar,
                    UserType = model.UserType,
                    Contact = model.Contact,
                    AddType=AddType.BackgroundAdd
                };

                if (model.UserType == UserType.Local)
                {
                    var result =  _userApp.Create(user, model.Password);
                    if (result.state!="success")
                    {
                        return Json(result);
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(postId))
                        {
                            var userPost = new UserPostModel();
                            userPost.UserId = _userApp.FindByNameAsync(user.UserName).Result.Id;
                            userPost.PostId = postId;
                            _userApp.AddToPosts(userPost.UserId, new string[1] { userPost.PostId });
                        }
                        return Success("操作成功!");
                    }
                }
                else
                {
                    var result = await _userApp.CreateAsync(user, "123456");
                    if (!result.Succeeded)
                    {
                        var sb = new System.Text.StringBuilder();
                        foreach (var err in result.Errors)
                        {
                            sb.Append(err.Description + "(" + err.Code + ")<br />");
                        }
                        return Error(sb.ToString());
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(postId))
                        {
                            var userPost = new UserPostModel();
                            userPost.UserId = _userApp.FindByNameAsync(user.UserName).Result.Id;
                            userPost.PostId = postId;
                            _userApp.AddToPosts(userPost.UserId, new string[1] { userPost.PostId });
                        }

                        return Success("操作成功!");
                    }
                }


            }
            return Json(Eqwww.Code.Common.ModelStateErrorResult(ModelState));
        }

        [AuthFilter]
        public IActionResult Edit(string id)
        {
            var model = new EditViewModel();
            if (string.IsNullOrEmpty(id))
                return NotFoundObject();
            var user = _userApp.FindByIdAsync(id).Result;
            if (user == null)
                return NotFoundObject();
            if (user.IsSystem == true)
                return ErrorView("系统用户不允许修改");

            model.Id = user.Id;
            model.Avatar = user.Avatar;
            model.Email = user.Email;
            model.UserName = user.UserName;
            model.RealName = user.RealName;
            model.SortCode = user.SortCode;
            model.UserType = user.UserType;
            model.Contact = user.Contact;
            

            return View(model);
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult Edit(string id, [Bind("Id, UserName, RealName, Contact, Password, RepeatPassword, UserType, SortCode, Avatar,  Email")] EditViewModel model)
        {
            if (string.IsNullOrEmpty(id))
                return Error("id不能为空!");
            if (id != model.Id)
                return Error("Get id和Post id不一致");

            var user = _userApp.FindByIdAsync(id).Result;
            if (user == null)
                return Error("未找到指定用户");

            if (ModelState.IsValid)
            {
                if (!string.IsNullOrEmpty(model.Password) && model.UserType == UserType.Local)
                {

                    var token = _userApp.GeneratePasswordResetTokenAsync(user).Result;
                    var r = _userApp.ResetPasswordAsync(user, token, model.Password).Result;

                }

                if (model.UserType == UserType.RTX)
                {
                    var token = _userApp.GeneratePasswordResetTokenAsync(user).Result;
                    var r = _userApp.ResetPasswordAsync(user, token, "123456").Result;
                }


                user.UserType = model.UserType;


                user.RealName = model.RealName;
                user.SortCode = model.SortCode;
                user.Email = model.Email;
                user.Avatar = model.Avatar;
                user.Contact = model.Contact;



                var result = _userApp.UpdateAsync(user).Result;
                if (!result.Succeeded)
                {
                    var sb = new System.Text.StringBuilder();
                    foreach (var err in result.Errors)
                    {
                        sb.Append(err.Description + "(" + err.Code + ")<br />");
                    }
                    return Error(sb.ToString());
                }
                else
                {
                    return Success("操作成功!");
                }
            }
            return Json(Eqwww.Code.Common.ModelStateErrorResult(ModelState));
        }

        [AuthFilter]
        public IActionResult CustomAvatar(string id)
        {
            return View();
        }

        [HttpPost]
        [AspNetCore.MultipartRequest.DisableFormValueModelBinding]
        public async Task<IActionResult> CustomAvatarSubmitAsync(string id)
        {
            if (string.IsNullOrEmpty(id))
                return Error("get id未传递有效参数.");

            var user = _userApp.FindByIdAsync(id).Result;
            if (user == null)
                return Error("未找到指定用户");

            var files = Request.Form.Files;
            var formFile = files[0];
            var path = Path.Combine(_hostingEnvironment.WebRootPath + "/upload/avatars/temps/" + System.Guid.NewGuid().ToString() + ".jpg");

            using (var stream = new FileStream(path, FileMode.CreateNew))
            {
                await formFile.CopyToAsync(stream);
            }

            var x = Request.Query["x"].ToString();
            var y = Request.Query["y"].ToString();
            var width = Request.Query["width"].ToString();
            var height = Request.Query["height"].ToString();

            var angle = new Rectangle(new Point(int.Parse(x), int.Parse(y)), new Size(int.Parse(width), int.Parse(height)));
            var avatarPath = "/upload/avatars/" + System.Guid.NewGuid().ToString() + ".jpg";

            using (var img = Image.Load(path))
            {
                using (Image<Rgba32> destRound = img.Clone(_ => _.Crop(angle)))
                {
                    destRound.Mutate(_ => _.Resize(256, 256));
                    destRound.Save(Path.Combine(_hostingEnvironment.WebRootPath + avatarPath));
                }
            }

            user.Avatar = avatarPath;
            var result = await _userApp.UpdateAsync(user);

            return Success(files.Count().ToString());

        }

        /// <summary>
        ///  将echarts返回的base64 转成图片
        /// </summary>
        /// <param name="image">图片的base64形式</param>
        private string SaveImage(string image)
        {
            string path = _hostingEnvironment.WebRootFileProvider + "/upload/avatars/temps/" + System.Guid.NewGuid().ToString() + ".jpg";
            string filepath = Path.GetDirectoryName(path);
            // 如果不存在就创建file文件夹
            if (!Directory.Exists(filepath))
            {
                if (filepath != null) Directory.CreateDirectory(filepath);
            }
            var match = System.Text.RegularExpressions.Regex.Match(image, "data:image/png;base64,([\\w\\W]*)$");
            if (match.Success)
            {
                image = match.Groups[1].Value;
            }
            var photoBytes = Convert.FromBase64String(image);
            System.IO.File.WriteAllBytes(path, photoBytes);

            return path;
        }

        [AuthFilter]
        public IActionResult Details(string id)
        {
            var model = new DetailsViewModel();
            if (string.IsNullOrEmpty(id))
                return NotFound();
            var user = _userApp.FindByIdAsync(id).Result;
            if (user == null)
                return NotFound();

            model.User = user;
            model.Roles = _userApp.GetRolesByUserId(user.Id);
            model.Strategorys = _userApp.GetStrategorysByUser(user.Id);
            model.Permissions = _userApp.GetPermissionsByUser(user.Id);
            return View(model);
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult UpdateDisabled(string userId)
        {
            return Json(_userApp.UpdateIsDisabled(userId, true));
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult UpdateEnabled(string userId)
        {
            return Json(_userApp.UpdateIsDisabled(userId, false));
        }

        [AuthFilter]
        public IActionResult PostRelation(string id)
        {
            var currentUser = _userApp.GetUserAsync(User).Result;
            var user = _userApp.FindByIdAsync(id).Result;

            if (_userApp.IsInRoleAsync(currentUser, "Founder").Result)
            {
                if (user == null)
                    ViewData["Items"] = _postApp.GetPostTreeCollapseToggleItems();
                else
                    ViewData["Items"] = _postApp.GetPostTreeCollapseToggleItemsByUserId(user.Id);
            }
            else if (_userApp.IsInRoleAsync(currentUser, "jsdwgly").Result)
            {
                var currentPostIds = from p in _context.Sys_UserPosts.Where(x => x.UserId == currentUser.Id) select p.PostId;
                var currentOrganizeIds = from p in _context.Sys_Posts.Where(x => x.DeleteMark != true && currentPostIds.Contains(x.Id)) select p.OrganizeId;
                var currentOrganizes = _context.Sys_Organizes.Where(x => currentOrganizeIds.Distinct().Contains(x.Id) && x.DeleteMark != true);



                if (user == null)
                {
                    var result = (from item in currentOrganizes
                                  select new TreeCollapseToggleModel
                                  {
                                      Id = item.Id,
                                      Text = item.Name,
                                      ParentId = null,
                                      SortCode = item.SortCode,
                                      Url = null,
                                      Disabled = true,
                                      CanToggle = false,
                                      Expend = true
                                  }).ToList();

                    var avaOrganizeIds = from p in currentOrganizes
                                         select p.Id;
                    var avaPosts = _context.Sys_Posts.Where(x => x.DeleteMark != true && avaOrganizeIds.Contains(x.OrganizeId));

                    result.AddRange((from item in avaPosts
                                     select new TreeCollapseToggleModel
                                     {
                                         Id = item.Id,
                                         Text = item.Name,
                                         ParentId = item.OrganizeId,
                                         SortCode = item.SortCode,
                                         Url = null,
                                         Disabled = false,
                                         CanToggle = true,
                                         Expend = true
                                     }).ToList());
                    ViewData["Items"] = result;
                }
                else
                {
                    var userPostIds = from p in _context.Sys_UserPosts.Where(x => x.UserId == user.Id) select p.PostId;

                    var result = (from item in currentOrganizes
                                  select new TreeCollapseToggleModel
                                  {
                                      Id = item.Id,
                                      Text = item.Name,
                                      ParentId = null,
                                      SortCode = item.SortCode,
                                      Url = null,
                                      Disabled = true,
                                      CanToggle = false,
                                      Expend = true
                                  }).ToList();

                    var avaOrganizeIds = from p in currentOrganizes
                                         select p.Id;
                    var avaPosts = _context.Sys_Posts.Where(x => x.DeleteMark != true && avaOrganizeIds.Contains(x.OrganizeId));

                    result.AddRange((from item in avaPosts
                                     select new TreeCollapseToggleModel
                                     {
                                         Id = item.Id,
                                         Text = item.Name,
                                         ParentId = item.OrganizeId,
                                         SortCode = item.SortCode,
                                         Url = null,
                                         Disabled = false,
                                         CanToggle = true,
                                         Expend = true
                                     }).ToList());

                    foreach (var p in result)
                    {
                        if (userPostIds.Contains(p.Id))
                        {
                            p.ToggleMark = true;
                        }
                    }

                    ViewData["Items"] = result;
                }

            }


            return View();
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult PostRelation(string userId, string permissions)
        {
            var ps = string.IsNullOrEmpty(permissions) ? new string[] { } : permissions.Split(',');
            return Json(_userApp.AddToPosts(userId, ps));
        }

        [AuthFilter]
        public IActionResult RoleRelation(string id)
        {


            var currentUser = _userApp.GetUserAsync(User).Result;
            if (_userApp.IsInRoleAsync(currentUser, "Founder").Result)
            {
                ViewData["Items"] = _userApp.GetRoleTreeCollapseToggleItemsByUserId(id);
            }
            else if (_userApp.IsInRoleAsync(currentUser, "jsdwgly").Result)
            {
                var data = (from p in _roleApp.Roles.Where(x => x.DeleteMark != true && (x.Name == "jsdwzgld" || x.Name == "jsdwzbglbm" || x.Name == "jsdwkszg" || x.Name == "jsdwywry")).OrderBy(x => x.SortCode)
                            select new TreeCollapseToggleModel
                            {
                                Id = p.Id,
                                CanToggle = true,
                                Disabled = false,
                                Expend = true,
                                ParentId = null,
                                SortCode = p.SortCode,
                                Text = p.ShowName,
                                Url = p.Description,
                                ToggleMark = false
                            }).ToList();
                var user = _userApp.FindByIdAsync(id).Result;
                foreach (var item in data)
                {
                    var role = _roleApp.FindByIdAsync(item.Id).Result;
                    item.ToggleMark = user == null ? false : _userApp.IsInRoleAsync(user, role.Name).Result;
                }

                ViewData["Items"] = data;
            }


            // ViewData["Items"] = _userApp.GetRoleTreeCollapseToggleItemsByUserId(id);
            return View();
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult RoleRelation(string userId, string permissions)
        {
            var ps = string.IsNullOrEmpty(permissions) ? new string[] { } : permissions.Split(',');
            return Json(_userApp.AddToRoles(userId, ps));
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult UpdateIsSystem(string id)
        {
            return Json(_userApp.UpdateIsSystem(id, true));
        }

        [HttpPost]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult UpdateIsNotSystem(string id)
        {
            return Json(_userApp.UpdateIsSystem(id, false));
        }

        // POST: SystemManage/Post/Delete/5
        [HttpPost, ActionName("Delete")]
        [ExceptionFilter]
        [ValidateAntiForgeryToken]
        public IActionResult DeleteConfirmed(string id)
        {
            var currentUser = _userApp.GetUserAsync(User).Result;

            return Json(_userApp.Remove(id, currentUser.Id));
        }

        public IActionResult GridJson(string keyword, UserType? userType, Pagination pagination)
        {
            var rows = _userApp.GetPagedList(keyword, userType, pagination);
            var data = new
            {
                rows = _mapper.Map<List<IndexViewModel>>(rows),
                total = pagination.total,
                page = pagination.page,
                records = pagination.records
            };
            return Content(data.ToJson());
        }
    }

    public class UploadAvatarModel
    {
        public IFormFile file1 { get; set; }
    }
}